package dm.ast.model.gen.factory;

import test.utility.Randomly;

import java.util.ArrayList;
import java.util.List;

/**
 * 生成查询列模板
 */
public class SelEleModelFactory extends BaseModelFactory{
    //根据深度、宽度，返回查询列模型
    public static ComplexityModel elementModels(int wid_t , int dep_t){
        List<ComplexityModel> models = new ArrayList<ComplexityModel>();

        //1、极值分配
        models.addAll(modelExtreme(wid_t , dep_t));

        //2、深度平均分配
        for (int i = 0; i < FactoryConstant.COUNT_AVERAGE; i++) {
            models.add(modelAverage(wid_t , dep_t));
        }

        return BaseModelFactory.getRanComplexityModel(models);
    }

    //极值分配
    public static List<ComplexityModel> modelExtreme(int wid_t , int dep_t){
        List<ComplexityModel> extreme = new ArrayList<ComplexityModel>();
        ComplexityModel model;

        //仅一个查询列
        model = new ComplexityModel(1);
        model.comps[0].wid_t = wid_t;
        model.comps[0].dep_t = dep_t;
        model.weight = FactoryConstant.WEIGHT_EXTREME;
        extreme.add(model);

        //2、大于一个查询列，随便选择一个查询列深度设为dep_t
        if(wid_t > 1 && dep_t > 1){
            extreme.add(modelExtremeDepth(wid_t , dep_t));
        }
        return extreme;
    }

    //深度极值分配
    //每个查询列都有同样的深度
    public static ComplexityModel modelExtremeDepth(int wid_t , int dep_t){
        int cnt = getRandomElementsCnt(wid_t , dep_t);
        ComplexityModel model = new ComplexityModel(cnt);

        int tmp_widt_used = 0;
        int i = 0;

        for (i = 0; i < model.count - 1; i++) {
            if((wid_t - tmp_widt_used) > FactoryConstant.MIN_WIDT_COMP){
                int tmp = r.getInteger(FactoryConstant.MIN_WIDT_COMP , wid_t - tmp_widt_used + 1);
                model.comps[i].wid_t = tmp;
                tmp_widt_used += tmp;
                model.comps[i].dep_t = dep_t;
            }else {
                model.comps[i].wid_t = wid_t - tmp_widt_used;
                tmp_widt_used += wid_t;
                model.comps[i].dep_t = dep_t;
            }
            if(tmp_widt_used >= wid_t){
                break;
            }
        }
        if(tmp_widt_used < wid_t){
            model.comps[i].wid_t = wid_t - tmp_widt_used;
            model.comps[i].dep_t = dep_t;
        }
        model.weight = FactoryConstant.WEIGHT_EXTREME;
        return model;
    }

    //平均分配
    public static ComplexityModel modelAverage(int wid_t , int dep_t){
        List<ComplexityModel> average = new ArrayList<ComplexityModel>();
        ComplexityModel model;
        int cnt = wid_t - estimateMinWidt(dep_t) + 1; //预设查询列个数
        if(cnt < 2){  //宽度相对于深度来说太小
            cnt = 2;  //最低设置2个查询列
        }

        model = BaseModelFactory.defaultModel(wid_t , dep_t , cnt);
        model.weight = FactoryConstant.WEIGHT_AVERAGE;
        return model;
    }

    //根据预期宽度、深度，返回合适的查询列个数
    private static int getRandomElementsCnt(int wid_t , int dep_t){
        int cnt = 1;
        if(wid_t < (FactoryConstant.MIN_WIDT_COMP * 2)){  //当预期宽度小于2倍的默认最小宽度时，直接生成1个查询列
            return cnt;
        }

        cnt = wid_t/FactoryConstant.MIN_WIDT_COMP;
        return cnt;
    }

}
